package com.apache.zuul.route;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.apache.cache.service.impl.redis.RedisCoreFactory;
import com.apache.tools.StrUtil;
import com.apache.zuul.config.FilterConfiguration;
import com.marcosbarbero.cloud.autoconfigure.zuul.ratelimit.config.RateLimitUtils;
import com.marcosbarbero.cloud.autoconfigure.zuul.ratelimit.config.properties.RateLimitProperties;
import com.marcosbarbero.cloud.autoconfigure.zuul.ratelimit.support.DefaultRateLimitKeyGenerator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.netflix.zuul.filters.Route;
import org.springframework.cloud.netflix.zuul.filters.ZuulProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;

import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;

/**
 * @description:
 * @author: Hou Dayu
 * @date: Created in 2020/3/17
 */
@Configuration
public class CustomZuulConfig {

    @Autowired
    ZuulProperties zuulProperties;
    @Autowired
    private Environment env;

    @Bean
    public CustomRouteLocator routeLocator() {
        CustomRouteLocator routeLocator = new CustomRouteLocator("/", this.zuulProperties);
        routeLocator.setJedisPool(initJedisPool());
        return routeLocator;
    }

    @Bean("jedisPool")
    public JedisPool initJedisPool() {
        Map<String, String> constant = new HashMap<String, String>();
        constant.put("redis_master_ip",getHost());
        constant.put("redis_master_port",env.getProperty("spring.redis.port"));
        constant.put("redis_auth",getAuth());
        constant.put("redis_maxActive",env.getProperty("spring.redis.jedis.pool.max-active"));
        constant.put("redis_maxIdle",env.getProperty("spring.redis.jedis.pool.max-idle"));
        constant.put("redis_maxWait",env.getProperty("spring.redis.jedis.pool.max-wait"));
        RedisCoreFactory.getInstance().setConstant(constant);
        return RedisCoreFactory.getInstance().getJedisPool();
    }
    private String getAuth(){
        return StrUtil.doNull(env.getProperty("spring.redis.password"),"14YVeC0PToxRIAs");
    }
    private String getHost(){
        return StrUtil.doNull(env.getProperty("spring.redis.host"),"localhost");
    }

    @Bean
    public DefaultRateLimitKeyGenerator rateLimitKeyGenerator(final RateLimitProperties properties, RateLimitUtils rateLimitUtils){
        return new DefaultRateLimitKeyGenerator(properties, rateLimitUtils){
            public String key(final HttpServletRequest request, final Route route, final RateLimitProperties.Policy policy){
                String key = request.getRequestURI();
                if(key.indexOf("/common/") == -1 && key.indexOf("/js/") == -1 && key.indexOf("/images/") == -1){
                    JSONObject routeJson = getRoute("", request.getHeader("req-service-id"));
                    if(StrUtil.isNotNull(routeJson.getString("rateLimit"))) {
                        policy.setLimit(routeJson.getLong("rateLimit"));
                    }
                    return key;
                }
                return null;
               // return super.key(request,route,policy);
            }
            private JSONObject getRoute(String spaceName, String serviceId){
                Jedis jedis = null;
                try{
                    jedis = RedisCoreFactory.getInstance().getJedis();
                    jedis.select(10);
                    String result = jedis.hget(StrUtil.doNull(spaceName,"zuul.routs"),serviceId);
                    if(StrUtil.isNotNull(result)){
                        return JSON.parseObject(result);
                    }
                }catch (Exception e){
                }finally{
                    if (null != jedis) {
                        jedis.close();
                    }
                }
                return new JSONObject();
            }
        };
    }
}

